#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.common.utils;


import ${package}.common.bean.po.DataTree;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * Description: 组织树工具类
 *
 * @author YL
 * @date 2019/8/6 15:28
 *
 * <pre>
 *              ${copyright}
 *      Copyright (c) 2019. All Rights Reserved.
 * </pre>
 */
public class TreeUtil {

    private TreeUtil() {
        // make constructor private
    }

    /**
     * Description:
     * <将平铺的节点转为树形存储-从顶端整理>
     * @param nodes         节点列表
     * @author wenxiaopeng
     * @date 21:45 2021/06/21
     * @return java.util.List<T>
     **/
    public static <T extends DataTree<T>> List<T> fillingTree(List<T> nodes) {
        return fillingTree(nodes, null);
    }

    /**
     * Description:
     * <将平铺的节点转为树形存储>
     * @param nodes         节点列表
     * @param fatherId      父节点ID，适用于从树的中间开始整理，若从顶端整理，则为null
     * @author wenxiaopeng
     * @date 21:45 2021/06/21
     * @return java.util.List<T>
     **/
    public static <T extends DataTree<T>> List<T> fillingTree(List<T> nodes, Long fatherId) {
        // 准备材料
        if(CollectionUtils.isNotEmpty(nodes)) {
            List<T> tops = nodes.stream().filter(item -> Objects.equals(fatherId,item.getParentId())).collect(Collectors.toList());
            Map<Long, List<T>> relations = nodes.stream().filter(item -> null != item.getParentId()).collect(Collectors.groupingBy(T::getParentId));
            // 递归
            fillingSubTree(tops, relations);
            return tops;
        }
        return nodes;
    }

    /**
     * Description:
     * <递归填充子树>
     * @param tops 1
     * @param relations 2
     * @author wenxiaopeng
     * @date 21:49 2021/06/21
     **/
    private static <T extends DataTree<T>> void fillingSubTree(List<T> tops, Map<Long, List<T>> relations) {
        if(CollectionUtils.isNotEmpty(tops)) {
            tops.forEach(vo -> {
                List<T> children = relations.get(vo.getId());
                if (null != children) {
                    vo.setChildList(children);
                    relations.remove(vo.getId());
                    fillingSubTree(children, relations);
                }
            });
        }
    }
}
